package net.lovesrc.allin.biz.stl;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.zhouzhou.fastjava.BizException;
import com.zhouzhou.fastjava.http.FilePart;
import com.zhouzhou.fastjava.http.MyHttpRequest;
import com.zhouzhou.fastjava.http.Requests;
import com.zhouzhou.fastjava.util.StringKit;
import com.zhouzhou.fastjava.util.ThreadKit;
import net.lovesrc.allin.biz.BaseService;
import net.lovesrc.allin.biz.NotificationService;
import net.lovesrc.allin.biz.idcard.IdCardService;
import net.lovesrc.support.service.imageverifycode.ImageVerifyCodeService;
import net.lovesrc.support.service.mobileverifycode.MobileVerifyCodeService;
import net.lovesrc.support.service.mobileverifycode.MobileVerifyCodeWrapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.CookieStore;
import org.apache.http.client.HttpClient;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.File;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

class BaseStlService extends BaseService {

    @Autowired
    private MobileVerifyCodeService mobileVerifyCodeService;

    @Autowired
    protected IdCardService idCardService;

    @Autowired
    protected ImageVerifyCodeService imageVerifyCodeService;

    protected MobileVerifyCodeWrapper getMobileVerifyCodeWrapper() {
        return new MobileVerifyCodeWrapper(mobileVerifyCodeService, "29947");
    }

    protected boolean isMyMobile(String mobile) {
        return jdbcTemplate.queryForObject("select count(1) from v_stl_my_account where mobile = ?", int.class, mobile) > 0;
    }

    protected boolean isNotMyMobile(String mobile) {
        return !isMyMobile(mobile);
    }

    protected void checkResJson(JSONObject resJson) {
        int status = resJson.getIntValue("status");
        int error = resJson.getIntValue("error");
        if (status == 1 && error == 0) {
            // is okay
        } else {
            throw BizException.messageOf(resJson.getString("content"));
        }
    }

    private String doLogin(JSONObject row) {
        String mobile = row.getString("mobile");
        CookieStore cookieStore = getCookieStore(mobile);
        HttpClient httpClient = newHttpClientWithMyProxy(mobile, cookieStore);
        getMobileVerifyCodeWrapper().getPhone(mobile);
        try {
            // send code
            JSONObject sendCodeResJson = MyHttpRequest.post(httpClient, "http://app.zaizhuji.cn/app/dong.php")
                    .param("act", "getVerifyCode2")
                    .param("mobile", mobile)
                    .execute()
                    .asJson();
            checkResJson(sendCodeResJson);
        } catch (Exception e) {
            getMobileVerifyCodeWrapper().releasePhone(mobile);
            throw e;
        }
        String verifyCode = getMobileVerifyCodeWrapper().getVerifyCodeFromPhone(mobile);
        JSONObject loginResJson = MyHttpRequest.post(httpClient, "http://app.zaizhuji.cn/app/login.php")
                .param("act", "act_login")
                .param("username", mobile)
                .param("password", row.getString("password"))
                .param("dxm", verifyCode)
                .param("device", row.getString("device"))
                .executeUtilReturn200()
                .asJson();
        int status = loginResJson.getIntValue("status");
        int error = loginResJson.getIntValue("error");
        if (status != 1 && error != 0) {
            throw BizException.messageOf(loginResJson.getString("content"));
        }
        String userId = loginResJson.getString("uid");
        String token = loginResJson.getString("token");
        JSONObject sets = new JSONObject()
                .fluentPut("userId", userId)
                .fluentPut("token", token)
                .fluentPut("cookies", Requests.toCookieString(cookieStore))
                .fluentPut("tokenTime", new Date())
                .fluentPut("verifyCode", verifyCode);
        updateRow(jdbcTemplate, "t_stl_account", sets, "mobile = ?", mobile);
        return token;
    }

    protected JSONObject post(String mobile, String url) {
        return this.post(mobile, url, new JSONObject());
    }

    protected JSONObject post(String mobile, String url, JSONObject params) {
        JSONObject row = queryForRow(jdbcTemplate, "select * from t_stl_account where mobile = ?", mobile);
        if (row == null) {
            throw BizException.messageOf("{} 在系统中不存在", mobile);
        }
        String cookies = row.getString("cookies");
        CookieStore cookieStore = Requests.toCookieStore(cookies);
        HttpClient httpClient;
        String paramAct = params.getString("act");
        if (url.contains("act=wdjy")
                || "wymr".equalsIgnoreCase(paramAct)
                || "jyjy".equalsIgnoreCase(paramAct)
                || url.contains("user.php")
        ) {
            httpClient = newHttpClientBuilder(cookieStore).build();
        } else {
            httpClient = newHttpClientWithMyProxy(mobile, cookieStore);
        }
        MyHttpRequest myHttpRequest = MyHttpRequest.post(httpClient, url);
        if (StringUtils.isNotBlank(row.getString("userId"))) {
            myHttpRequest.param("user_id", row.getString("userId"));
        }
        if (StringUtils.isNotBlank(row.getString("token"))) {
            myHttpRequest.param("token", row.getString("token"));
        }
        if (StringUtils.isNotBlank(row.getString("device"))) {
            myHttpRequest.param("device", row.getString("device"));
        }
        myHttpRequest.params(params);

        JSONObject resJson = null;
        for (int i = 0; i < 5; i++) {
            resJson = myHttpRequest
                    .executeUtilReturn200()
                    .asJson();
            if (resJson == null) {
                continue;
            }
            String code = resJson.getString("code");
            // 代理的问题
            if (StringUtils.isNotBlank(code)) {
                continue;
            }
            break;
        }

        if (resJson == null) {
            throw BizException.messageOf("接口返回异常，返回为NULL");
        }

        // 未登录
        int status = resJson.getIntValue("status");
        int error = resJson.getIntValue("error");
        String content = resJson.getString("content");
        if (status == 0 && error == 0 && StringUtils.isBlank(content)) {
            if ("success".equalsIgnoreCase(row.getString("idStatus"))) {
                try {
                    doLogin(row);
                    return post(mobile, url, params);
                } catch (Exception e) {
                    jdbcTemplate.update("update t_stl_account set worked = 2, mark = ? where mobile = ?", e.getMessage(), mobile);
                    throw e;
                }
            }
        }
        return resJson;
    }


    protected JSONObject postDong(String mobile, String act) {
        return this.postDong(mobile, act, new JSONObject());
    }

    protected JSONObject postDong(String mobile, String act, JSONObject params) {
        params.put("act", act);
        return this.post(mobile, "http://app.zaizhuji.cn/app/dong.php", params);
    }

    public List<JSONObject> getMyKjs(String mobile) {
        List<Element> items = doGetMyKjDoms(mobile);
        List<JSONObject> kjs = Lists.newArrayList();
        for (Element item : items) {
            String id = StringKit.extract(item.text(), "编号：(\\d+)");
            String name = item.selectFirst(".name").text();
            String status = item.selectFirst(".status").text();
            String text = item.selectFirst(".text").text();
            kjs.add(
                    new JSONObject()
                            .fluentPut("id", id)
                            .fluentPut("name", name)
                            .fluentPut("status", status)
                            .fluentPut("text", text)
            );
        }
        for (StlKjKind kjKind : StlKjKind.values()) {
            List<JSONObject> kjsOfThisKind = kjs.stream()
                    .filter(row -> row.getString("name").contains(kjKind.getName()))
                    .collect(Collectors.toList());
            if (kjKind.isUnlimitedRunning()) {
                kjsOfThisKind.stream()
                        .filter(row -> isNotUsed(row))
                        .forEach(row -> runningKj(mobile, row));
            } else {
                long runningQty = kjsOfThisKind.stream()
                        .filter(row -> isRunningKj(row))
                        .count();
                for (int i = 0; i < kjKind.getMaxQty() - runningQty; i++) {
                    JSONObject notUsedKj = kjsOfThisKind
                            .stream()
                            .filter(row -> isNotUsed(row))
                            .findFirst()
                            .orElse(null);
                    if (notUsedKj == null) {
                        break;
                    }
                    this.runningKj(mobile, notUsedKj);
                }
            }
        }
        this.updateUserKjs(mobile, kjs);
        return kjs;
    }

    // 运行中和未使用
    protected boolean isWorkKj(JSONObject row) {
        return isRunningKj(row) || isNotUsed(row);
    }

    // 运行中
    private boolean isRunningKj(JSONObject row) {
        String status = row.getString("status");
        return status.contains("运行中");
    }

    private boolean isNotUsed(JSONObject row) {
        String status = row.getString("status");
        return status.contains("未使用");
    }

    protected void doPay(String mobile, int kjId) {
        this.postDong(mobile, "pay", new JSONObject().fluentPut("kj_id", kjId));
        ThreadKit.sleepSeconds(2);
    }

    protected void doPay2(String mobile, int kjId) {
        JSONObject resJson = this.postDong(mobile, "pay2", new JSONObject().fluentPut("kj_id", kjId));
        ThreadKit.sleepSeconds(2);
        try {
            checkResJson(resJson);
        } catch (BizException e) {
            if (e.getMessage().contains("您的STZ不足")) {
                notificationService.syncEmail(NotificationService.LZQ_EMAIL, "您的STZ不足");
            } else {
                throw e;
            }
        }
    }

    private void runningKj(String mobile, JSONObject row) {
        this.postDong(mobile, "yxkj",
                new JSONObject()
                        .fluentPut("userkj_id", row.getString("id"))
        );
        row.put("status", "运行中");
    }

    private List<Element> doGetMyKjDoms(String mobile) {
        List<Element> doms = Lists.newArrayList();
        for (int page = 1; page <= 100; page++) {
            JSONObject resJson = this.post(mobile, "http://app.zaizhuji.cn/app/member/user.php?act=wdkj&page=" + page);
            checkResJson(resJson);

            String content = resJson.getString("content");
            if (StringUtils.isBlank(content) || content.contains("暂无记录")) {
                break;
            }

            Document doc = Jsoup.parse(content);
            Elements pageItems = doc.select(".item");
            doms.addAll(pageItems);
            if (pageItems.size() < 10) {
                break;
            }
        }
        return doms;
    }

    private void updateUserKjs(String mobile, List<JSONObject> kjs) {
        for (JSONObject kj : kjs) {
            JSONObject row = new JSONObject()
                    .fluentPutAll(kj);
            row.put("mobile", mobile);
            int id = kj.getIntValue("id");
            if (jdbcTemplate.queryForObject("select count(1) from t_stl_kj where id = ?", long.class, id) == 0) {
                insertRow(jdbcTemplate, "t_stl_kj", row);
            } else {
                row.remove("id");
                updateRow(jdbcTemplate, "t_stl_kj", row, "id = ?", id);
            }
        }
    }

    public String uploadFile(String mobile, File file) {

        if (file == null || !file.exists()) {
            throw BizException.messageOf("上传的图片不存在");
        }

        JSONObject row = queryForRow(jdbcTemplate, "select * from t_stl_account where mobile = ?", mobile);
        String cookies = row.getString("cookies");
        CookieStore cookieStore = Requests.toCookieStore(cookies);
        HttpClient httpClient = newHttpClientWithMyProxy(mobile, cookieStore);

        FilePart filePart = FilePart.builder()
                .name("filename")
                .contentType("image/jpeg")
                .filename(UUID.randomUUID().toString().toUpperCase() + ".jpg")
                .file(file)
                .build();
        JSONObject resJson = MyHttpRequest.post(httpClient, "http://app.zaizhuji.cn/app/sp.php")
                .param("act", "smrz")
                .part(filePart)
                .executeUtilReturn200()
                .asJson();
        return resJson.getString("filename");
    }

    public boolean isNotJyTime() {
        return !isJyTime();
    }

    public boolean isJyTime() {
        String jyTime = tryGetProperties(String.class, "10-19", "Stl_Jy_Time");
        int minJyTime = Integer.valueOf(jyTime.split("-")[0]);
        int maxJyTime = Integer.valueOf(jyTime.split("-")[1]);
        int nowTime = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
        return nowTime >= minJyTime && nowTime < maxJyTime;
    }

}
